﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using ModelClassesLinqToSql.Domain.Models;
using System.Reflection;

namespace ModelClassesLinqToSql.Domain.Repositories
{
    public class MovieRepository : IMovieRepository
    {
        private PrototypeDataContext dataContext;

        public MovieRepository()
        {
            this.dataContext = new PrototypeDataContext();
        }

        public IQueryable<Movie> GetAll()
        {
            return (from m in this.dataContext.Movies
                    orderby m.Name
                    select m);
        }

        public IQueryable<MovieEmployeeJobTitleComposite> GetMoviesAndDirectors()
        {
            return (from m in this.dataContext.Movies
                    from e in this.dataContext.Employees
                    from jt in this.dataContext.JobTitles
                    join mejt in this.dataContext.MovieEmployeeJobTitles on
                        new { MovieId = m.Id, EmployeeId = e.Id, JobTitleId = jt.Id } equals new { mejt.MovieId, mejt.EmployeeId, mejt.JobTitleId }
                    where jt.Id == 1
                    orderby m.Name
                    select new MovieEmployeeJobTitleComposite() {
                        Movie = m, 
                        Employee = e, 
                        JobTitle = jt
                    });
        }

        public IQueryable<EmployeeJobTitleComposite> GetMovieEmployees(int movieId, IEnumerable<Enums.EmployeeType> employeeTypes = null)
        {
            //build complete anonymous result set
            var rs = from m in this.dataContext.Movies
                     from e in this.dataContext.Employees
                     from jt in this.dataContext.JobTitles
                     join mejt in this.dataContext.MovieEmployeeJobTitles on
                         new { MovieId = m.Id, EmployeeId = e.Id, JobTitleId = jt.Id } equals new { mejt.MovieId, mejt.EmployeeId, mejt.JobTitleId }
                     where m.Id == movieId
                     select new { m, e, jt };

            //if employee types provided filter by them
            if (employeeTypes != null)
            {
                IEnumerable<int> et = (employeeTypes.Select(e => (int)e));

                rs = from r in rs
                     where et.Contains(r.jt.Id)
                     select r;
            }

            //return final typed collection
            return (from f in rs
                    orderby f.e.FirstName, f.e.LastName, f.jt.Title
                    select new EmployeeJobTitleComposite()
                    {
                        Employee = f.e,
                        JobTitle = f.jt
                    });
        }

        /*public EmployeeJobTitleComposite GetMovieEmployee(int movieId, int employeeId, int jobTitleId)
        {
            return (from ejc in this.GetMovieEmployees(movieId)
                    where ejc.Employee.Id == employeeId
                        && ejc.JobTitle.Id == jobTitleId
                    select ejc).FirstOrDefault();
        }*/

        public Movie GetMovie(int movieId)
        {
            return (from m in this.dataContext.Movies
                    where m.Id == movieId
                    select m).FirstOrDefault();
        }

        public void AssignMovieEmployee(MovieEmployeeJobTitle movieEmployeeJobTitle)
        {
            this.dataContext.MovieEmployeeJobTitleInsert(
                movieEmployeeJobTitle.MovieId,
                movieEmployeeJobTitle.EmployeeId,
                movieEmployeeJobTitle.JobTitleId
            );
            //this.dataContext.MovieEmployeeJobTitles.InsertOnSubmit(movieEmployeeJobTitle);
        }

        public void UnassignMovieEmployee(MovieEmployeeJobTitle movieEmployeeJobTitle)
        {
            this.dataContext.MovieEmployeeJobTitleDelete(
                movieEmployeeJobTitle.MovieId,
                movieEmployeeJobTitle.EmployeeId,
                movieEmployeeJobTitle.JobTitleId
            );
            /*MovieEmployeeJobTitle origEJ = (
                 from mej in this.dataContext.MovieEmployeeJobTitles
                 where mej.MovieId == movieEmployeeJobTitle.MovieId
                     && mej.EmployeeId == movieEmployeeJobTitle.EmployeeId
                     && mej.JobTitleId == movieEmployeeJobTitle.JobTitleId
                 select mej
            ).First();

            this.dataContext.MovieEmployeeJobTitles.DeleteOnSubmit(origEJ);*/
        }

        public void SaveMovie()
        {
            this.dataContext.SubmitChanges();
        }
    }
}